package mao.thinkinjava.io;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**
 * idea 开发环境问题，开发环境有缓存，
 */
public class LockingMappedFiles {
    private static MappedByteBuffer mbb;
    private static FileChannel fc;
    private static int LENGTH = 0x80;

    public static void main (String[] args) throws IOException,InterruptedException {
        new LockingMappedFiles();
    }
    LockingMappedFiles() throws IOException, InterruptedException {
        fc = new RandomAccessFile("LockMappedFile.txt", "rw").getChannel();
        System.out.println(fc.position());
        mbb = fc.map(FileChannel.MapMode.READ_WRITE,0,LENGTH);
        System.out.println(mbb.position());
        for (int i = 0; i < LENGTH; i++) {
            System.out.println(mbb.position());
            mbb.put((byte)'m');
        }
        Thread thread_1 = new LockAndModify(mbb,0,LENGTH/4);
        Thread thread_2 = new LockAndModify(mbb,LENGTH/2,LENGTH/2+LENGTH/4);
        thread_1.start();
        thread_2.start();
        thread_1.join();
        thread_2.join();
        fc.close();
    }
    private static class LockAndModify extends Thread {
        private int start,end;
        private ByteBuffer bb;
        LockAndModify(MappedByteBuffer mbb,int start,int end){
            this.start = start;
            this.end = end;
            //limit 必须要大于position否则报错。
            mbb.limit(end);
            mbb.position(start);
            bb = mbb.slice();
        }

        @Override
        public void run() {
            FileLock fileLock;
            try {
                 fileLock= fc.lock(start,end,false);
                 System.out.format("lockfile from %d to %d\n",start,end);
                 while (bb.position()<bb.limit()-1){
                     bb.put((byte)(bb.get()+1));
                 }
                 fileLock.release();
                 System.out.println("release"+start+"  "+end+"\n");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
